package com.zx.system.block.controller.system;

import com.zx.core.wrapper.ListWrapper;
import com.zx.core.wrapper.ObjectWrapper;
import com.zx.core.wrapper.PageWrapper;
import com.zx.core.wrapper.ResponseWrapper;
import com.zx.feign.client.dto.GetSysUserResponseDTO;
import com.zx.log.annotation.OperateLog;
import com.zx.security.block.uitls.SecurityUtils;
import com.zx.security.common.model.LoginUser;
import com.zx.system.block.model.SysDept;
import com.zx.system.block.model.SysMenu;
import com.zx.system.block.model.SysRole;
import com.zx.system.block.model.SysUser;
import com.zx.system.block.param.ChangePasswordParam;
import com.zx.system.block.param.UserParam;
import com.zx.system.block.param.UserPostParam;
import com.zx.system.block.param.UserRoleParam;
import com.zx.system.block.service.*;
import com.zx.system.block.vo.SysPostVO;
import com.zx.system.block.vo.SysUserVO;
import com.zx.validation.annotation.ParameterValidation;
import com.zx.validation.annotation.ParameterValidations;
import com.zx.validation.enums.ValidateRulesEnum;
import com.zx.validation.groups.Create;
import com.zx.validation.groups.Query;
import com.zx.validation.groups.StatusUpdate;
import com.zx.validation.groups.Update;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * description: 用户信息 <br>
 * create: 2024-08-23 23:51
 * </p>
 *
 * @author zhou  xun
 */
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class SysUserController {
    private final ISysDeptService iSysDeptService;
    private final ISysUserService iSysUserService;
    private final ISysMenuService iSysMenuService;
    private final ISysRoleService iSysRoleService;
    private final ISysPostService iSysPostService;

    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("/getInfo")
    public ObjectWrapper<Map<String, Object>> getInfo() {
        ObjectWrapper<Map<String, Object>> result = new ObjectWrapper<>();
        // 获取当前认证信息
        Authentication authentication = SecurityUtils.getAuthentication();
        // 从认证信息中获取用户ID
        String userId = ((LoginUser) authentication.getPrincipal()).getId();
        // 获取用户信息
        SysUser sysUser = iSysUserService.selectUserById(userId);

        Map<String, Object> responseData = new HashMap<>();
        responseData.put("user", sysUser);

        // 获取部门信息
        if (sysUser.getDeptId() != null && !sysUser.getDeptId().isEmpty()) {
            SysDept sysDept = iSysDeptService.selectDeptById(sysUser.getDeptId());
            if (sysDept != null) {
                responseData.put("deptName", sysDept.getName());
            }
        }

        // 获取角色信息
        ListWrapper<SysRole> roleListWrapper = iSysRoleService.selectRoleInfos(sysUser.getId());
        if (roleListWrapper.verifyFail()) {
            result.fail(roleListWrapper.getMsg());
            return result;
        }
        responseData.put("roles", Optional.ofNullable(roleListWrapper.getData())
                .orElse(Collections.emptyList()).stream()
                .map(SysRole::getRoleKey)
                .collect(Collectors.toList()));

        // 添加角色名称列表
        responseData.put("roleNames", Optional.ofNullable(roleListWrapper.getData())
                .orElse(Collections.emptyList()).stream()
                .map(SysRole::getName)
                .collect(Collectors.toList()));

        // 获取岗位信息
        ListWrapper<SysPostVO> postListWrapper = iSysPostService.selectPostVOListByUserId(sysUser.getId());
        if (postListWrapper.verifyFail()) {
            result.fail(postListWrapper.getMsg());
            return result;
        }
        responseData.put("postNames", Optional.ofNullable(postListWrapper.getData())
                .orElse(Collections.emptyList()).stream()
                .map(SysPostVO::getPostName)
                .collect(Collectors.toList()));

        // 获取权限信息
        ListWrapper<SysMenu> menuListWrapper = iSysMenuService.selectSysMenuInfos(sysUser.getId());
        responseData.put("permissions",
                Optional.ofNullable(menuListWrapper.getData())
                        .orElse(Collections.emptyList()).stream()
                        .map(SysMenu::getPerms)
                        .collect(Collectors.toList()));
        result.setData(responseData);
        return result;
    }

    /**
     * 获取指定用户信息
     * 供Feign客户端调用
     */
    @OperateLog(value = "获取指定用户信息")
    @GetMapping("/info/{userName}")
    public ObjectWrapper<LoginUser> getUserInfo(@PathVariable("userName") String userName) {
        ObjectWrapper<LoginUser> result = new ObjectWrapper<>();
        SysUser sysUser = iSysUserService.selectUserByLoginCredential(userName);
        if (Objects.isNull(sysUser)) {
            result.fail("用户不存在");
            return result;
        }
        ListWrapper<SysRole> roleListWrapper = iSysRoleService.selectRoleInfos(sysUser.getId(), sysUser.getName());
        if (roleListWrapper.verifyFail()) {
            result.fail(roleListWrapper.getMsg());
            return result;
        }
        // 角色集合
        Set<String> roleSet = roleListWrapper.getData().stream()
                .map(SysRole::getRoleKey)
                .collect(Collectors.toSet());

        ListWrapper<SysMenu> menuListWrapper = iSysMenuService.selectSysMenuInfos(sysUser.getId(), sysUser.getName());
        if (menuListWrapper.verifyFail()) {
            result.fail(menuListWrapper.getMsg());
            return result;
        }
        //权限集合
        Set<String> permsSet = menuListWrapper.getData().stream()
                .map(SysMenu::getPerms)
                .collect(Collectors.toSet());

        //LoginUser loginUser = new LoginUser(sysUser.getId(), sysUser.getName(), sysUser.getPassword(), roleSet, permsSet, sysUser.getStatus(), sysUser.getTenantId());
        result.setData(loginUser);
        return result;
    }

    /**
     * 根据登录凭证获取用户信息
     * 供Feign客户端调用
     */
    @OperateLog(value = "根据登录凭证获取用户信息")
    @GetMapping("/info/credential/{loginCredential}")
    public ObjectWrapper<LoginUser> getUserInfoByLoginCredential(@PathVariable("loginCredential") String loginCredential) {
        ObjectWrapper<LoginUser> result = new ObjectWrapper<>();
        SysUser sysUser = iSysUserService.selectUserByLoginCredential(loginCredential);
        if (Objects.isNull(sysUser)) {
            result.fail("用户不存在");
            return result;
        }
        ListWrapper<SysRole> roleListWrapper = iSysRoleService.selectRoleInfos(sysUser.getId(), sysUser.getName());
        if (roleListWrapper.verifyFail()) {
            result.fail(roleListWrapper.getMsg());
            return result;
        }
        // 角色集合
        Set<String> roleSet = roleListWrapper.getData().stream()
                .map(SysRole::getRoleKey)
                .collect(Collectors.toSet());

        ListWrapper<SysMenu> menuListWrapper = iSysMenuService.selectSysMenuInfos(sysUser.getId(), sysUser.getName());
        if (menuListWrapper.verifyFail()) {
            result.fail(menuListWrapper.getMsg());
            return result;
        }
        //权限集合
        Set<String> permsSet = menuListWrapper.getData().stream()
                .map(SysMenu::getPerms)
                .collect(Collectors.toSet());

        LoginUser loginUser = new LoginUser(sysUser.getId(), sysUser.getName(), sysUser.getPassword(), roleSet, permsSet, sysUser.getStatus(), sysUser.getTenantId());
        result.setData(loginUser);
        return result;
    }

    @PreAuthorize("hasAuthority('system:user:list')")
    @PostMapping("/list")
    @ParameterValidations(
            @ParameterValidation(index = 0, desc = "用户参数", rules = {ValidateRulesEnum.OBJECT}, groups = {Query.class})
    )
    public PageWrapper<SysUserVO> list(@RequestBody UserParam userParam) {
        return iSysUserService.getUserVOListByPage(userParam);
    }

    /**
     * 新增用户
     *
     * @param userParam 用户信息
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2024-10-29
     */
    @PreAuthorize("hasAuthority('system:user:add')")
    @OperateLog(value = "新增用户")
    @PostMapping("/addUser")
    @ParameterValidations(
            @ParameterValidation(index = 0, desc = "用户参数", rules = {ValidateRulesEnum.OBJECT}, groups = {Create.class})
    )
    public ResponseWrapper addUser(@RequestBody UserParam userParam) {
        return iSysUserService.addUser(userParam);
    }

    /**
     * 编辑用户
     *
     * @param userParam 用户信息
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2024-10-29
     */
    @PreAuthorize("hasAuthority('system:user:edit')")
    @OperateLog(value = "编辑用户")
    @PutMapping("/editUser")
    @ParameterValidations(
            @ParameterValidation(index = 0, desc = "用户参数", rules = {ValidateRulesEnum.OBJECT}, groups = {Update.class})
    )
    public ResponseWrapper editUser(@RequestBody UserParam userParam) {
        return iSysUserService.editUser(userParam);
    }

//    /**
//     * 修改用户状态
//     *
//     * @param jsonStr 参数json字符串
//     * @return {@link ResponseWrapper}
//     * @author zhou  xun
//     * @since 2024-10-29
//     */
//    @PreAuthorize("hasAuthority('system:user:edit')")
//    @OperateLog(value = "修改用户状态")
//    @PutMapping("/editUserStatus")
//    public ResponseWrapper editUserStatus(@RequestBody String jsonStr) {
//        ObjectWrapper<UserParam> objectWrapper = JsonStrUtils.checkParseObject(jsonStr, UserParam.class);
//        if (!objectWrapper.verifySuccess()) {
//            return objectWrapper;
//        }
//        UserParam userParam = objectWrapper.getData();
//        return iSysUserService.editUserStatus(userParam.getId(), userParam.getStatus());
//    }

    /**
     * 修改用户状态
     *
     * @param userParam 用户参数
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2024-10-29
     */
    @PreAuthorize("hasAuthority('system:user:edit')")
    @OperateLog(value = "修改用户状态")
    @PutMapping("/editUserStatus")
    @ParameterValidations(
            @ParameterValidation(index = 0, desc = "用户参数", rules = {ValidateRulesEnum.OBJECT}, groups = {StatusUpdate.class})
    )
    public ResponseWrapper editUserStatus(@RequestBody UserParam userParam) {
        return iSysUserService.editUserStatus(userParam.getId(), userParam.getStatus());
    }

    /**
     * 删除用户
     *
     * @param userId 用户Id
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2024-10-29
     */
    @PreAuthorize("hasAuthority('system:user:remove')")
    @OperateLog(value = "删除用户")
    @DeleteMapping("/deleteUser/{userId}")
    @ParameterValidations({
            @ParameterValidation(index = 0, desc = "用户Id", rules = {ValidateRulesEnum.NOT_NULL})
    })
    public ResponseWrapper deleteUser(@PathVariable("userId") String userId) {
        return iSysUserService.deleteUser(userId);
    }

    /**
     * 获取用户信息
     * 供Feign客户端调用
     *
     * @param userId 用户Id
     * @return {@link ObjectWrapper<SysUser>}
     * @author zhou  xun
     * @since 2024-10-29
     */
    @ParameterValidations({
            @ParameterValidation(index = 0, desc = "用户Id", rules = {ValidateRulesEnum.NOT_NULL})
    })
    @GetMapping("/{userId}")
    public ObjectWrapper<GetSysUserResponseDTO> getUserInfoById(@PathVariable("userId") String userId) {
        return iSysUserService.getUserById(userId);
    }

    /**
     * 重置密码
     *
     * @param userParam 用户参数
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2025-04-13
     */
    @PreAuthorize("hasAuthority('system:user:resetPwd')")
    @OperateLog(value = "重置密码")
    @PutMapping("/resetUserPwd")
    // 移除参数验证注解，因为业务层已经进行了充分的验证
    public ResponseWrapper resetUserPwd(@RequestBody UserParam userParam) {
        return iSysUserService.resetUserPwd(userParam);
    }

    /**
     * 获取用户的角色信息
     *
     * @param userId 用户id
     * @return {@link ObjectWrapper}
     * @author zhou  xun
     * @since 2025-04-14
     */
    @OperateLog(value = "获取用户的角色信息")
    @GetMapping("/getUserRoleIdList/{userId}")
    @ParameterValidations({
            @ParameterValidation(index = 0, desc = "用户Id", rules = {ValidateRulesEnum.NOT_NULL})
    })
    public ObjectWrapper<Set<String>> getUserRoleIdList(@PathVariable("userId") String userId) {
        return iSysUserService.selectRoleIdsByUserId(userId);
    }

    /**
     * 分配角色
     *
     * @param userRoleParam 用户角色参数
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2025-04-13
     */
    @PreAuthorize("hasAuthority('system:user:setUserRole')")
    @OperateLog(value = "分配角色")
    @PutMapping("/setUserRole")
    @ParameterValidations(
            @ParameterValidation(index = 0, desc = "用户角色参数", rules = {ValidateRulesEnum.OBJECT})
    )
    public ResponseWrapper setUserRole(@RequestBody UserRoleParam userRoleParam) {
        return iSysUserService.setUserRole(userRoleParam.getUserId(), userRoleParam.getRoleIds());
    }

    /**
     * 分配岗位
     *
     * @param userPostParam 用户岗位参数
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2025-04-13
     */
    @PreAuthorize("hasAuthority('system:user:setUserPost')")
    @OperateLog(value = "分配岗位")
    @PutMapping("/setUserPost")
    @ParameterValidations(
            @ParameterValidation(index = 0, desc = "用户岗位参数", rules = {ValidateRulesEnum.OBJECT})
    )
    public ResponseWrapper setUserPost(@RequestBody UserPostParam userPostParam) {
        return iSysUserService.setUserPost(userPostParam.getUserId(), userPostParam.getPostIds());
    }

    /**
     * 修改密码
     *
     * @param changePasswordParam 修改密码参数
     * @return {@link ResponseWrapper}
     */
    @OperateLog(value = "修改密码")
    @PutMapping("/changePassword")
    @ParameterValidations(
            @ParameterValidation(index = 0, desc = "修改密码参数", rules = {ValidateRulesEnum.OBJECT})
    )
    public ResponseWrapper changePassword(@RequestBody ChangePasswordParam changePasswordParam) {
        // 获取当前用户ID
        String userId = SecurityUtils.getUserId();
        return iSysUserService.changePassword(userId, changePasswordParam.getOldPassword(), changePasswordParam.getNewPassword());
    }
}